/**
 * Copyright (C) 2018-2022
 * All rights reserved, Designed By www.yixiang.co
 * 注意：
 * 本软件为www.yixiang.co开发研制
 */
package co.yixiang.modules.mp.serviceimpl;




// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import co.yixiang.common.enums.ResultCode;
import co.yixiang.common.exception.BadRequestException;
import co.yixiang.common.exception.ServiceException;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.FileUtil;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.modules.adopt.entity.domain.YxAdoptCategory;
import co.yixiang.modules.adopt.entity.vo.YxAdoptCategoryVo;
import co.yixiang.modules.mp.entity.domain.YxArticle;
import co.yixiang.modules.mp.entity.domain.YxArticleCategory;
import co.yixiang.modules.mp.entity.dto.YxArticleCategoryDto;
import co.yixiang.modules.mp.entity.dto.YxArticleCategoryQueryCriteria;
import co.yixiang.modules.mp.entity.enums.ArticleEnum;
import co.yixiang.modules.mp.entity.vo.YxArticleCategoryVo;
import co.yixiang.modules.mp.entity.vo.YxArticleCategoryVoF;
import co.yixiang.modules.mp.mapper.ArticleCategoryMapper;
import co.yixiang.modules.mp.service.YxArticleCategoryService;
import co.yixiang.modules.mp.service.YxArticleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hupeng
 * @date 2020-05-12
 */
@Service
//@CacheConfig(cacheNames = "yxArticle")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxArticleCategoryServiceImpl extends BaseServiceImpl<ArticleCategoryMapper, YxArticleCategory> implements YxArticleCategoryService {

    @Autowired
    private IGenerator generator;
    @Autowired
    private YxArticleService articleService;

    /**
     * 顶级父分类ID
     */
    private String parentId = "0";
    /**
     * 最大分类等级
     */
    private int maxLevel = 2;

    @Override
    public List<YxArticleCategoryVoF> queryAllByVo(YxArticleCategoryQueryCriteria criteria) {
        QueryWrapper predicate = QueryHelpPlus.getPredicate(YxArticleCategory.class, criteria);
        predicate.orderByDesc("sort");
        return generator.convert(baseMapper.selectList(predicate),YxArticleCategoryVoF.class);
    }

    @Override
    public Map<String, Object> queryAll(YxArticleCategoryQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<YxArticleCategory> page = new PageInfo<>(queryAll(criteria));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", generator.convert(page.getList(), YxArticleCategoryDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
    public List queryAll(YxArticleCategoryQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(YxArticleCategory.class, criteria));
    }


    @Override
    public void download(List<YxArticleCategoryDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (YxArticleCategoryDto yxArticle : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("分类名称", yxArticle.getName());
            map.put("层级", yxArticle.getLevel());
            map.put("上级分类ID", yxArticle.getParentId());
            map.put("排序", yxArticle.getSort());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
    
    /**
     * 构建菜单树
     *
     * @param articleCategoryDtos 原始数据
     * @return /
     */
    @Override
    public Map<String, Object> buildTree(List<YxArticleCategoryDto> articleCategoryDtos) {
        List<YxArticleCategoryDto> trees = new ArrayList<>();
        Set<Long> ids = new HashSet<>();
        for (YxArticleCategoryDto YxArticleCategoryDto : articleCategoryDtos) {
            if (YxArticleCategoryDto.getParentId() == 0) {
                trees.add(YxArticleCategoryDto);
            }
            for (YxArticleCategoryDto it : articleCategoryDtos) {
                if (it.getParentId().equals(YxArticleCategoryDto.getId())) {
                    if (YxArticleCategoryDto.getChildren() == null) {
                        YxArticleCategoryDto.setChildren(new ArrayList<>());
                    }
                    YxArticleCategoryDto.getChildren().add(it);
                    ids.add(it.getId());
                }
            }
        }
        Map<String, Object> map = new HashMap<>(2);
        if (trees.size() == 0) {
            trees = articleCategoryDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
        }
        map.put("content", trees);
        map.put("totalElements", articleCategoryDtos.size());
        return map;
    }

    /**
     * 构建菜单树
     *
     * @param yxArticleCategoryDtos /
     * @return /
     */
    @Override
    public List<YxArticleCategoryVo> buildYxArticleCategorys(List<YxArticleCategoryDto> yxArticleCategoryDtos) {
        List<YxArticleCategoryVo> list = new LinkedList<>();
        yxArticleCategoryDtos.forEach(yxArticleCategoryDTO -> {
                    if (yxArticleCategoryDTO != null) {
                        List<YxArticleCategoryDto> YxArticleCategoryDtoList = yxArticleCategoryDTO.getChildren();
                        YxArticleCategoryVo YxArticleCategoryVo = new YxArticleCategoryVo();
                        YxArticleCategoryVo.setName(yxArticleCategoryDTO.getName());
                        // 一级目录需要加斜杠，不然会报警告
                        YxArticleCategoryVo.setHidden(yxArticleCategoryDTO.getHidden());
                        // 如果不是外链
                        if (YxArticleCategoryDtoList != null && YxArticleCategoryDtoList.size() != 0) {
                            YxArticleCategoryVo.setAlwaysShow(true);
                            YxArticleCategoryVo.setChildren(buildYxArticleCategorys(YxArticleCategoryDtoList));
                            // 处理是一级菜单并且没有子菜单的情况
                        } else if (yxArticleCategoryDTO.getParentId() == 0) {
                            YxArticleCategoryVo YxArticleCategoryVo1 = new YxArticleCategoryVo();
                            // 非外链
                            YxArticleCategoryVo1.setName(YxArticleCategoryVo.getName());
                            YxArticleCategoryVo.setName(null);
                            List<YxArticleCategoryVo> list1 = new ArrayList<>();
                            list1.add(YxArticleCategoryVo1);
                            YxArticleCategoryVo.setChildren(list1);
                        }
                        list.add(YxArticleCategoryVo);
                    }
                }
        );
        return list;
    }

    /**
     * 获取菜单树
     *
     * @param YxArticleCategorys /
     * @return /
     */
    @Override
    public Object getYxArticleCategoryTree(List<YxArticleCategory> YxArticleCategorys) {
        List<Map<String, Object>> list = new LinkedList<>();
        YxArticleCategorys.forEach(YxArticleCategory -> {
                    if (YxArticleCategory != null) {
                        List<YxArticleCategory> YxArticleCategoryList = findByPid(YxArticleCategory.getId());
                        Map<String, Object> map = new HashMap<>(16);
                        map.put("id", YxArticleCategory.getId());
                        map.put("label", YxArticleCategory.getName());
                        if (YxArticleCategoryList != null && YxArticleCategoryList.size() != 0) {
                            map.put("children", getYxArticleCategoryTree(YxArticleCategoryList));
                        }
                        list.add(map);
                    }
                }
        );
        return list;
    }

    /**
     * 获取待删除的菜单
     *
     * @param YxArticleCategoryList /
     * @param YxArticleCategorySet  /
     * @return /
     */
    @Override
    public Set<YxArticleCategory> getDeleteYxArticleCategorys(List<YxArticleCategory> YxArticleCategoryList, Set<YxArticleCategory> YxArticleCategorySet) {
        // 递归找出待删除的菜单
        for (YxArticleCategory YxArticleCategory1 : YxArticleCategoryList) {
            YxArticleCategorySet.add(YxArticleCategory1);
            List<YxArticleCategory> YxArticleCategorys = findByPid(YxArticleCategory1.getId());
            if (YxArticleCategorys != null && YxArticleCategorys.size() != 0) {
                getDeleteYxArticleCategorys(YxArticleCategorys, YxArticleCategorySet);
            }
        }
        return YxArticleCategorySet;
    }

    /**
     * 根据pid查询
     *
     * @param pid /
     * @return /
     */
    @Override
    public List<YxArticleCategory> findByPid(long pid) {
        return list(new LambdaQueryWrapper<YxArticleCategory>().eq(YxArticleCategory::getParentId, pid));
    }


    /**
     * 删除
     *
     * @param YxArticleCategorySet /
     */
    @Override
    public void delete(Set<YxArticleCategory> YxArticleCategorySet) {
        List<Long> ids = new ArrayList<>(YxArticleCategorySet.size());
        for (YxArticleCategory articleCategory : YxArticleCategorySet) {
            // 判断是否为默认的分类
            if (!articleCategory.getType().equals(ArticleEnum.OTHER.name())) {
                throw new ServiceException(ResultCode.ARTICLE_CATEGORY_NO_DELETION);
            }
            ids.add(articleCategory.getId());
        }
        //查看文章分类下是否有分类
        final Long count = this.lambdaQuery().in(YxArticleCategory::getParentId, ids).count();
        if (count > 0) {
            throw new ServiceException(ResultCode.ARTICLE_CATEGORY_DELETE_ERROR);
        }
        final List<YxArticle> list = articleService.list(new LambdaQueryWrapper<YxArticle>().in(YxArticle::getCid, ids));
        if(CollectionUtil.isNotEmpty(list)) {
            throw new BadRequestException("分类下有文章不能删除");
        }
        removeBatchByIds(ids);
    }

    /**
     * 编辑
     *
     * @param resources /
     */
    @Override
    public void update(YxArticleCategory resources) {
        if (resources.getId().equals(resources.getParentId())) {
            throw new BadRequestException("上级不能为自己!");
        }
        // 要修改的数据是否存在
        YxArticleCategory YxArticleCategory = this.getById(resources.getId());
        if (ObjectUtil.isEmpty(YxArticleCategory)) {
            throw new BadRequestException("修改的分类不存在!");
        }
        // 校验父节点和层级
        isExitParent(resources);
        //验证分类名称是否重复, 同层级下不能有重复的
        final YxArticleCategory category = this.getOne(new QueryWrapper<YxArticleCategory>().eq("name", resources.getName()));
        if (category != null && category.getParentId().equals(resources.getParentId()) && !category.getId().equals(resources.getId())) {
            throw new ServiceException(ResultCode.ARTICLE_CATEGORY_NAME_EXIST);
        }
        this.saveOrUpdate(YxArticleCategory);
    }

    @Override
    public YxArticleCategoryDto create(YxArticleCategory resources) {
        final YxArticleCategory exitParent = isExitParent(resources);
        if (ObjectUtil.isNotEmpty(exitParent)) {
            resources.setLevel(resources.getLevel() + 1);
        }
        //验证分类名称是否重复, 同层级下不能有重复的
        final YxArticleCategory category = this.getOne(new LambdaQueryWrapper<YxArticleCategory>().eq(YxArticleCategory::getName, resources.getName()));
        if (category != null && category.getParentId().equals(resources.getParentId())) {
            throw new ServiceException(ResultCode.ARTICLE_CATEGORY_NAME_EXIST);
        }
        // resources.setType(ArticleCategoryEnum.OTHER.name());
        this.save(resources);
        return generator.convert(resources, YxArticleCategoryDto.class);
    }
    /**
     * 公共方法提取出来-判断父级元素是否存在，和检查层级不能大于2
     * @param resources
     */
    private YxArticleCategory isExitParent(YxArticleCategory resources) {
        if (resources.getParentId() != null && !parentId.equals(resources.getParentId())) {
            // 非顶级,返回父类
            YxArticleCategory parent = this.getById(resources.getParentId());
            if (parent == null) {
                throw new ServiceException(ResultCode.ARTICLE_CATEGORY_PARENT_NOT_EXIST);
            }
//            if (resources.getLevel() > maxLevel) {
//                throw new ServiceException(ResultCode.ARTICLE_CATEGORY_BEYOND_TWO);
//            }
            return parent;
        }
        // 顶级，返回空
        return null;
    }




}
